<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>旋转六边形弹球</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }
        canvas {
            display: block;
            background: #f0f0f0;
        }
    </style>
</head>
<body>
    <canvas id="gameCanvas"></canvas>
    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        resizeCanvas();
        window.addEventListener('resize', resizeCanvas);

        // 物理参数
        const GRAVITY = 0.2;
        const FRICTION = 0.98;
        const BALL_RADIUS = 12;
        const HEX_RADIUS = 220;
        let rotationSpeed = 0.015;
        let lastTimestamp = 0;
        let cycleTimer = 0;
        let isAccelerating = true;
        let isStopped = false;
        const SPEED_CHANGE_INTERVAL = 3000; // 5秒
        const ORIGINAL_SPEED = 0.015;

        let balls = [];

        function resetGame() {
            balls = [];
            ballCounter = 0;
            rotationSpeed = ORIGINAL_SPEED;
            isStopped = false;
            isAccelerating = true;
            cycleTimer = 0;
            
            // 创建初始小球（1个）
            balls.push({
                x: canvas.width/2,
                y: canvas.height/2 - HEX_RADIUS/1.5,
                dx: Math.random()*4-2,
                dy: Math.random()*4-2,
                color: COLORS[0]
            });
        }

        // 初始化游戏
        function initGame() {
            document.getElementById('resetButton').addEventListener('click', resetGame);
            resetGame();
            
            // 初始化动画循环
            requestAnimationFrame((ts) => {
                lastTimestamp = ts;
                update(ts);
            });
        }
        
        // 确保DOM加载完成后初始化游戏
        window.addEventListener('DOMContentLoaded', initGame);
        
        const COLORS = ['#FF5252', '#FF4081', '#E040FB', '#7C4DFF', '#536DFE', '#448AFF', '#40C4FF', '#18FFFF', '#64FFDA', '#69F0AE'];
        let ballCounter = 1;
        const BALL_SPAWN_INTERVAL = 500;
        let spawnInterval = setInterval(() => {
            if (ballCounter < 9) {
                const angle = Math.random() * Math.PI * 2;
                balls.push({
                    x: canvas.width/2,
                    y: canvas.height/2,
                    dx: Math.cos(angle) * (1 + Math.random() * 0.5),
                    dy: Math.sin(angle) * (1 + Math.random() * 0.5),
                    color: COLORS[ballCounter % COLORS.length]
                });
                ballCounter++;
                if(ballCounter > 9) {
                    clearInterval(spawnInterval);
                }
            }
        }, BALL_SPAWN_INTERVAL);

        let rotation = 0;

        function getHexVertices() {
            const vertices = [];
            for(let i=0; i<6; i++) {
                const angle = Math.PI/3 * i + rotation;
                vertices.push({
                    x: canvas.width/2 + HEX_RADIUS * Math.cos(angle),
                    y: canvas.height/2 + HEX_RADIUS * Math.sin(angle)
                });
            }
            return vertices;
        }

        function checkCollision() {
            const vertices = getHexVertices();
            
            // 小球与六边形碰撞
            balls.forEach(ball => {
                for(let i=0; i<6; i++) {
                    const p1 = vertices[i];
                    const p2 = vertices[(i+1)%6];
                    
                    // 线段方程计算
                    const edgeVec = {x: p2.x - p1.x, y: p2.y - p1.y};
                    const normal = {x: -edgeVec.y, y: edgeVec.x};
                    const len = Math.sqrt(normal.x**2 + normal.y**2);
                    normal.x /= len;
                    normal.y /= len;

                    // 碰撞检测
                    const ballToEdge = {
                        x: ball.x - p1.x,
                        y: ball.y - p1.y
                    };
                    const distance = ballToEdge.x * normal.x + ballToEdge.y * normal.y;

                    // 检测与边的碰撞
                    if(distance < BALL_RADIUS) {
                        // 速度反射
                        const dot = ball.dx * normal.x + ball.dy * normal.y;
                        ball.dx -= 2 * dot * normal.x;
                        ball.dy -= 2 * dot * normal.y;

                        // 位置修正
                        ball.x += normal.x * (BALL_RADIUS - distance);
                        ball.y += normal.y * (BALL_RADIUS - distance);
                    }
                    
                    // 检测与半圆的碰撞
                    const midX = (p1.x + p2.x)/2;
                    const midY = (p1.y + p2.y)/2;
                    const dx = ball.x - midX;
                    const dy = ball.y - midY;
                    const distToSemicircle = Math.sqrt(dx*dx + dy*dy);
                    
                    if(distToSemicircle < BALL_RADIUS + 40) {
                        // 计算碰撞法向量
                        const nx = dx/distToSemicircle;
                        const ny = dy/distToSemicircle;
                        
                        // 速度反射（弹性系数1.5倍）
                        const dot = ball.dx * nx + ball.dy * ny;
                        ball.dx -= 2 * dot * nx;
                        ball.dy -= 2 * dot * ny;
                        
                        // 位置修正
                        ball.x += nx * (BALL_RADIUS + 40 - distToSemicircle);
                        ball.y += ny * (BALL_RADIUS + 40 - distToSemicircle);
                    }
                }
            });
            
            // 小球之间碰撞
            for(let i=0; i<balls.length; i++) {
                for(let j=i+1; j<balls.length; j++) {
                    const ball1 = balls[i];
                    const ball2 = balls[j];
                    const dx = ball2.x - ball1.x;
                    const dy = ball2.y - ball1.y;
                    const distance = Math.sqrt(dx*dx + dy*dy);
                    
                    if(distance < BALL_RADIUS*2) {
                        // 计算碰撞法向量
                        const nx = dx/distance;
                        const ny = dy/distance;
                        
                        // 计算相对速度
                        const vx = ball2.dx - ball1.dx;
                        const vy = ball2.dy - ball1.dy;
                        
                        // 计算冲量
                        const impulse = (vx*nx + vy*ny) / 2;
                        
                        // 更新速度（弹性系数1.5倍）
                        ball1.dx += impulse * nx;
                        ball1.dy += impulse * ny;
                        ball2.dx -= impulse * nx;
                        ball2.dy -= impulse * ny;
                        
                        // 防止小球重叠
                        const overlap = BALL_RADIUS*2 - distance;
                        ball1.x -= overlap * nx / 2;
                        ball1.y -= overlap * ny / 2;
                        ball2.x += overlap * nx / 2;
                        ball2.y += overlap * ny / 2;
                    }
                }
            }
        }

        function update(timestamp) {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // 物理模拟
            balls.forEach(ball => {
                ball.dy += GRAVITY;
                ball.x += ball.dx;
                ball.y += ball.dy;
                ball.dx *= FRICTION;
                ball.dy *= FRICTION;
            });

            checkCollision();
            rotation += rotationSpeed;
            
            // 变速逻辑(已注释)
            /*
            // 调试输出timestamp值
            ctx.fillStyle = '#000';
            ctx.font = '14px Arial';
            ctx.fillText(`变速触发: 速度:${rotationSpeed.toFixed(3)}  加速:${isAccelerating}  停止:${isStopped}`, 20, 30);
            ctx.fillText(`当前时刻: ${(timestamp/1000).toFixed(1)}s  上一时刻: ${(lastTimestamp/1000).toFixed(1)}s  差值: ${((timestamp - lastTimestamp)/1000).toFixed(1)}s`, 20, 60);
            //ctx.fillText(`小球1位置: x: ${balls[0].x.toFixed(1)}  y: ${balls[0].y.toFixed(1)}`, 20, 90);
            //ctx.fillText(`小球1速度: dx: ${balls[0].dx.toFixed(3)}  dy: ${balls[0].dy.toFixed(3)}`, 20, 120);
            
            cycleTimer = timestamp - lastTimestamp;
            
            if (cycleTimer > SPEED_CHANGE_INTERVAL) {
                // 在画布上显示调试信息
                cycleTimer = 0;
                lastTimestamp = timestamp;
                if (isStopped) {
                    isStopped = false;
                    isAccelerating = true;
                    rotationSpeed = ORIGINAL_SPEED;
                } else {
                    isAccelerating = !isAccelerating;
                    if (!isAccelerating) {
                        rotationSpeed = 0;
                        isStopped = true;
                    } else {
                        rotationSpeed = ORIGINAL_SPEED;
                    }
                }
            }
            */

            // 绘制六边形
            drawHexagonWithSemicircles();
            
            function drawHexagonWithSemicircles() {
                const vertices = getHexVertices();
                ctx.strokeStyle = '#4CAF50';
                ctx.lineWidth = 3;
                
                // 绘制六边形边
                ctx.beginPath();
                vertices.forEach((p,i) => {
                    i === 0 ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y);
                });
                ctx.closePath();
                ctx.stroke();
                
                // 为每条边添加半圆形障碍物
                ctx.fillStyle = '#00008B';
                for(let i=0; i<6; i++) {
                    const p1 = vertices[i];
                    const p2 = vertices[(i+1)%6];
                    
                    // 计算边的中点
                    const midX = (p1.x + p2.x)/2;
                    const midY = (p1.y + p2.y)/2;
                    
                    // 计算边的角度
                    const angle = Math.atan2(p2.y - p1.y, p2.x - p1.x);
                    
                    // 绘制半圆（直径放大一倍，直边与六边形边平行）
                    ctx.beginPath();
                    ctx.arc(midX, midY, 40, angle + Math.PI, angle, true);
                    ctx.fill();
                }
            }

            // 绘制小球
            // 显示小球数量
            ctx.fillStyle = '#000';
            ctx.font = '16px Arial';
            ctx.fillText(`小球数量: ${balls.length}`, canvas.width - 120, 30);
            


            // 更新和绘制小球
            balls.forEach(ball => {
                ctx.fillStyle = ball.color;
                ctx.beginPath();
                ctx.arc(ball.x, ball.y, BALL_RADIUS, 0, Math.PI*2);
                ctx.fill();
            });

            requestAnimationFrame(update);
        }

        // 初始化动画循环
        requestAnimationFrame((ts) => {
            lastTimestamp = ts;
            update(ts);
        });
    </script>
<button id="resetButton" style="position: fixed; bottom: 20px; right: 20px; padding: 10px 20px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">初始化</button>
</body>
</html>